Exploring Qutebrowser 6:send weibo with commands
I'm exploring the source code of Qutebrowser. In this post, I will write a custom command to send a Weibo.
Core Steps
- create a custom command function
- get the user input by function parameter
- navigate current tab to target site
- find the inputarea, and input text
- click send!
Command Function
Most of the commands are under qutebrowser/browser/commands.py
. So I will apend my code to this source file:
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('content')
def weibo(self, content=None):
# write my code here
pass
The content
parameter will contain the content input by the user.
Modify AbstractTab
I modified the source code of Qutebrowser AbstractTab
, adding a listening callback mechanism to help commands listen for the completion of web page loading. In the AbstractTab
class:
First add a class field:
on_load_finish_cbs: List[Callable[[bool], None]] = []
Then in the _on_load_finished
method, add the following code:
@pyqtSlot(bool)
def _on_load_finished(self, ok: bool) -> None:
assert self._widget is not None
if self.is_deleted():
# https://github.com/qutebrowser/qutebrowser/issues/3498
return
# the code to add
for cb in self.on_load_finish_cbs:
cb(ok)
#...
Navigating the Tab
The CommandDispatcher
provides a _cntwidget
method to get current browser tab. Then we call the load_url
to navigate our tab to Weibo Website.
@cmdutils.register(instance='command-dispatcher', scope='window')
@cmdutils.argument('content')
def weibo(self, content=None):
cur_tab: browsertab.AbstractTab = self._cntwidget()
def on_load_finish(ok: bool):
cur_tab.on_load_finish_cbs.remove(on_load_finish)
print('on_load_finish')
cur_tab.on_load_finish_cbs.append(on_load_finish)
cur_tab.load_url(QUrl('https://weibo.com'))
When the page is loaded, the on_load_finish
will be called.
Finding the Inputarea
In the on_load_finish
method, I added the following code to find the inputarea. When it was found, I use the insert_text
method of AbstractWebElement
for inputing.
def on_load_finish(ok: bool):
print(f'on_load_finish {cur_tab.url().toString()}')
cur_tab.on_load_finish_cbs.remove(on_load_finish)
selector = webelem.css_selector('inputs', url)
print(f'css selector: {selector}')
def on_find_input(elems: Sequence[AbstractWebElement]):
for elem in elems:
classes = elem.classes()
found = False
for cls in classes:
if cls.startswith('Form_input'):
found = True
break
if not found:
continue
elem.insert_text(content)
print(f'find input: {elem.outer_xml()}')
# elem.insert_text(content)
cur_tab.elements.find_css(
selector,
on_find_input,
lambda e: print(f'find input error: {e}'))
Clicking Send
First we need to find the click button. We will use the QuteBrowser's css_selector
method again.
def on_find_send(send_elems: Sequence[AbstractWebElement]):
send_template = '<span class="woo-button-content">发送</span>'
for send_elem in send_elems:
send_classes = send_elem.classes()
send_found = False
for _ in send_classes:
if send_template in send_elem.outer_xml():
send_found = True
break
if not send_found:
continue
send_elem.click(usertypes.ClickTarget.normal)
selector_send = webelem.css_selector('all', url)
cur_tab.elements.find_css(
selector_send,
on_find_send,
lambda e: print(f'find send error: {e}'))
The code is almost the same. I use a piece of HTML code to identify the send button. I think there's a better way to find the button, but the code above just works :)
Bingo!
It's very cool! If you want to create a command for Twitter/X, It's the same way. See you at my next blog!
本文作者:Maeiee
本文链接:Exploring Qutebrowser 6:send weibo with commands
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!